#!/usr/bin/env python3  # 设置脚本可直接执行
# -*- coding:utf-8 -*-   # 设置文件编码为UTF-8
"""
@Author: zhuo
@Software: PyCharm
@File: tJLinkHelper.py
@Time: 2025/6/16 17:23
@Function：tJLinkHelper:J-Link通讯模块
"""

# 导入所需模块
import os  # 操作系统功能
import sys
import time  # 时间相关功能
import json  # JSON数据处理
import struct  # 二进制数据结构处理
import subprocess  # 运行外部进程
import threading  # 多线程支持
from pylink import JLink, JLinkInterfaces  # J-Link SDK接口
from PySide6.QtCore import Signal, QObject, QTimer  # Qt信号和定时器


# 资源路径函数 - 解决打包后路径问题
def resource_path(relative_path):
    """获取打包后资源的绝对路径"""
    try:
        # PyInstaller创建的临时文件夹
        base_path = sys._MEIPASS
    except Exception:
        base_path = os.path.abspath(os.path.dirname(__file__))

    return os.path.join(base_path, relative_path)


# 设置J-Link路径
j_link_dir = resource_path("dll")
os.environ["PATH"] = os.pathsep.join([os.environ["PATH"], j_link_dir])


# 实时传输(RTT)通信读取器
class RTTReader:
    """
    function:  实时传输(RTT)通信读取器
          in:  jlink: JLink对象实例
               control_block_addr: RTT控制块地址(可选)
               buffer_size: 缓冲区大小(默认4096)
         out:  无
      return:  RTTReader实例
      others:  用于通过RTT协议与目标设备通信
    """

    # 初始化函数
    def __init__(self, j_link, control_block_addr=None, buffer_size=4096):
        self.j_link = j_link  # JLink连接对象
        self.control_block_addr = control_block_addr  # RTT控制块地址
        self.buffer_size = buffer_size  # 缓冲区大小
        self.rtt_started = False  # RTT启动状态标志

    # 自动搜索RTT控制块地址函数
    def f_findControlBlockFunc(self, start_addr=0x20000000, end_addr=0x20100000, search_step=4096):
        """
        function:  自动搜索RTT控制块地址
              in:  start_addr: 搜索起始地址(默认0x20000000)
                   end_addr: 搜索结束地址(默认0x20100000)
                   search_step: 搜索步长(默认4096)
             out:  无
          return:  找到的控制块地址或None
          others:  通过内存签名"SEGGER RTT"定位控制块
        """
        signature = b"SEGGER RTT"  # RTT控制块标识签名

        # 尝试搜索已知地址列表
        known_addresses = [
            0x20000000, 0x20000400, 0x20000800, 0x20000C00,
            0x20001000, 0x20002000, 0x20003000, 0x20004000,
            0x20005000, 0x20006000, 0x20007000, 0x20008000,
            0x20009000, 0x2000A000, 0x2000B000, 0x2000C000,
            0x2000D000, 0x2000E000, 0x2000F000
        ]

        # 遍历已知地址检查签名
        for addr in known_addresses:
            try:
                # 从内存读取签名长度的数据
                data = self.j_link.memory_read(addr, len(signature))
                if data == signature:  # 检查是否匹配签名
                    return addr  # 返回找到的地址
            except:
                continue  # 忽略错误继续搜索

        # 线性搜索内存区域
        addr = start_addr  # 从起始地址开始
        while addr < end_addr:  # 遍历到结束地址
            try:
                # 读取内存数据
                data = self.j_link.memory_read(addr, len(signature))
                if data == signature:  # 检查是否匹配签名
                    return addr  # 返回找到的地址
            except:
                pass  # 忽略访问错误
            addr += search_step  # 移动到下一个搜索位置

        return None  # 未找到控制块

    # 启动RTT通信函数
    def f_startRttFunc(self):
        """
        function:  启动RTT通信
              in:  无
             out:  无
          return:  True表示成功，否则抛出异常
          others:  如果未提供控制块地址，会自动搜索
        """
        if not self.control_block_addr:  # 如果未提供控制块地址
            # 尝试自动查找控制块
            self.control_block_addr = self.f_findControlBlockFunc()
            if not self.control_block_addr:  # 未找到控制块
                raise Exception("未找到RTT控制块地址 - 请确保在目标固件中启用了RTT")

        try:
            # 设置控制块地址
            self.j_link.rtt_control_block_address = self.control_block_addr

            # 启动RTT
            self.j_link.rtt_start()
            self.rtt_started = True  # 更新启动状态

            # 检查RTT是否成功启动
            time.sleep(0.1)  # 等待设备响应
            if not self.j_link.rtt_is_started():  # 验证启动状态
                raise Exception("RTT启动失败 - 可能是设备未启用RTT支持")

            return True  # 启动成功
        except Exception as e:
            raise Exception(f"启动RTT失败: {str(e)} - 请检查控制块地址和设备RTT配置")

    # 停止RTT通信函数
    def f_stopRttFunc(self):
        """
        function:  停止RTT通信
              in:  无
             out:  无
          return:  无
          others:  安全停止RTT通信
        """
        if self.rtt_started:  # 如果RTT已启动
            try:
                self.j_link.rtt_stop()  # 停止RTT
                self.rtt_started = False  # 更新状态
            except:
                pass  # 忽略停止错误

    # 读取RTT缓冲区函数
    def f_readRttFunc(self, buffer_index=0, size=None):
        """
        function:  从RTT缓冲区读取数据
              in:  buffer_index: 缓冲区索引(默认0)
                   size: 要读取的大小(默认缓冲区大小)
             out:  无
          return:  读取到的数据或None
          others:  从指定缓冲区读取数据
        """
        if not self.rtt_started:  # 检查RTT状态
            return None

        try:
            if size is None:  # 如果未指定大小
                size = self.buffer_size  # 使用默认缓冲区大小

            # 从RTT缓冲区读取数据
            data = self.j_link.rtt_read(buffer_index, size)
            return data  # 返回读取的数据
        except Exception as e:
            return None  # 读取失败

    # 写入RTT缓冲区函数
    def f_writeRttFunc(self, buffer_index=0, data=None):
        """
        function:  向RTT缓冲区写入数据
              in:  buffer_index: 缓冲区索引(默认0)
                   data: 要写入的数据
             out:  无
          return:  True表示成功，False表示失败
          others:  向指定缓冲区写入数据
        """
        if not self.rtt_started or not data:  # 检查RTT状态和数据有效性
            return False

        try:
            self.j_link.rtt_write(buffer_index, data)  # 写入数据
            return True  # 写入成功
        except:
            return False  # 写入失败


# J-Link通信类
class ctJLinkHelper(QObject):
    """
    function:  J-Link通信类
          in:  无
         out:  无
      return:  ctJLinkHelper实例
      others:  提供与J-Link适配器交互的完整功能，支持RTT和异步两种模式
    """

    # <editor-fold desc="定义各种信号">
    log_signal = Signal(str)  # 日志信号
    list_devices_result = Signal(list)  # 设备列表结果信号
    connect_result = Signal(bool, str)  # 连接结果信号
    disconnect_done = Signal()  # 断开连接完成信号
    chip_info_ready = Signal(str, str, str, str)  # 芯片信息就绪信号
    adapter_info_ready = Signal(str, str, str, str, str)  # 适配器信息就绪信号
    memory_read_result = Signal(int, int)  # 内存读取结果信号
    memory_write_done = Signal(int, int)  # 内存写入完成信号
    register_read = Signal(int, int)  # 寄存器读取信号
    error_occurred = Signal(str)  # 错误发生信号
    param_values_ready = Signal(dict)  # 参数值就绪信号
    monitoring_status = Signal(bool)  # 监控状态信号
    rtt_status_changed = Signal(bool)  # RTT状态变化信号
    monitor_timer_updated = Signal(float)  # 监控定时器更新信号
    # </editor-fold>

    # <editor-fold desc="初始化类变量">
    read_failure_count = 0  # 读取失败计数器

    # </editor-fold>

    # 初始化函数
    def __init__(self):
        super().__init__()  # 调用父类构造函数
        self.j_link = None  # J-Link连接对象
        self.lock = threading.RLock()  # 可重入锁，用于线程安全
        self.params_config = {}  # 参数配置字典
        self.monitored_params = []  # 监控参数列表
        self.monitoring_active = False  # 监控激活状态
        self.monitor_timer = None  # 监控定时器
        self._connection_params = {}  # 连接参数存储
        self._optimal_speed = 30000  # 优化后的连接速度(kHz)

        # RTT相关属性
        self.rtt_reader = None  # RTT读取器实例
        self.rtt_control_block_addr = None  # RTT控制块地址
        self.rtt_active = False  # RTT活动状态
        self.rtt_data_map = {}  # RTT数据映射
        self.read_mode = "rtt"  # 读取模式，默认为RTT
        self.old_driver = False  # 旧驱动标志

        # 连接状态跟踪
        self.read_failure_count = 0  # 读取失败次数计数器
        self.last_successful_read = time.time()  # 上次成功读取时间戳

    # 记录日志函数
    def f_logFunc(self, message):
        """
        function:  记录日志消息
              in:  message: 要记录的字符串消息
             out:  无
          return:  无
          others:  通过log_signal信号发送消息
        """
        self.log_signal.emit(message)  # 发射日志信号

    # <editor-fold desc="连接/断开J-Link">
    # 连接J-Link函数
    def f_connectJLinkFunc(self, device, interface, speed):
        """
        function:  连接J-Link适配器
              in:  device: 目标设备名称
                   interface: 接口类型(SWD/JTAG等)
                   speed: 连接速度(kHz)
             out:  无
          return:  连接成功返回True，否则返回False
          others:  支持自动重连和RTT初始化
        """

        def _connect():
            """内部连接函数"""
            try:
                # 存储连接参数
                self._connection_params = {
                    "device": device,
                    "interface": interface,
                    "speed": speed
                }
                self._optimal_speed = speed  # 设置优化速度

                # 关闭现有连接
                if self.j_link:
                    self.j_link.close()

                # 创建新J-Link实例
                self.j_link = JLink()
                self.f_logFunc(f"正在打开J-Link连接，速度: {speed} kHz...")
                self.j_link.open()  # 打开连接

                # 设置接口类型
                iface = getattr(JLinkInterfaces, interface.upper(), JLinkInterfaces.SWD)
                self.f_logFunc(f"设置接口: {interface.upper()} ({iface})")
                self.j_link.set_tif(iface)  # 设置目标接口

                # 设置连接速度
                self.f_logFunc(f"设置接口速度: {speed} kHz")
                self.j_link.set_speed(speed)

                try:
                    # 尝试连接设备
                    self.f_logFunc(f"尝试连接设备: {device}")
                    self.j_link.connect(device, speed)
                except Exception as e:
                    # 处理不支持设备的情况
                    if "unsupported device" in str(e).lower():
                        return self.__f_connectCortexMFunc(device, speed)
                    raise  # 重新抛出异常

                # 连接后设置
                self.__f_postConnectSetupFunc()

                # 初始化RTT
                self.rtt_reader = RTTReader(self.j_link, self.rtt_control_block_addr)
                try:
                    if self.rtt_reader.f_startRttFunc():  # 启动RTT
                        self.f_logFunc("RTT通信已启动")
                        self.rtt_active = True
                        self.read_mode = "rtt"  # 设置读取模式为RTT
                    else:
                        self.f_logFunc("警告: RTT启动失败，将使用异步批量读取模式")
                        self.rtt_active = False
                        self.read_mode = "async"  # 设置读取模式为异步
                except Exception as e:
                    self.f_logFunc(f"警告: {str(e)}，将使用异步批量读取模式")
                    self.rtt_active = False
                    self.read_mode = "async"

                # 发射RTT状态信号
                self.rtt_status_changed.emit(self.rtt_active)

                return True  # 连接成功
            except Exception as e:
                self.f_logFunc(f"连接错误: {str(e)}")
                # 清理连接
                if self.j_link:
                    try:
                        self.j_link.close()
                    except:
                        pass
                    self.j_link = None
                return False  # 连接失败

        # 使用锁确保线程安全
        with self.lock:
            if self.__f_executeWithRetryFunc(_connect):  # 带重试执行连接
                self.connect_result.emit(True, device)  # 发射连接成功信号
                return True
            self.connect_result.emit(False, "连接失败")  # 发射连接失败信号
            return False

    # 断开J-Link连接函数
    def f_disconnectJLinkFunc(self):
        """
        function:  断开J-Link连接
              in:  无
             out:  无
          return:  成功断开返回True，否则返回False
          others:  安全停止所有活动并关闭连接
        """

        def _disconnect():
            """内部断开函数"""
            try:
                if self.j_link:
                    self.f_stopMonitoringFunc()  # 停止监控
                    if self.rtt_reader:
                        self.rtt_reader.f_stopRttFunc()  # 停止RTT
                        self.rtt_active = False
                        self.rtt_status_changed.emit(False)  # 发射状态变化
                    self.j_link.close()  # 关闭连接
                    self.f_logFunc("已断开连接")
                return True
            except Exception as e:
                self.f_logFunc(f"断开连接时出错: {str(e)}")
                return False

        with self.lock:  # 线程安全
            if self.__f_executeWithRetryFunc(_disconnect):  # 带重试执行
                self.disconnect_done.emit()  # 发射断开完成信号
                return True
            return False

    # 同步断开J-Link连接函数
    def f_disconnectJLinkSyncFunc(self):
        """
        function:  同步断开J-Link连接
              in:  无
             out:  无
          return:  成功返回True，否则返回False
          others:  安全断开连接并清理资源
        """
        try:
            if self.j_link:
                # 停止RTT
                if self.rtt_reader:
                    self.rtt_reader.f_stopRttFunc()
                    self.rtt_active = False

                # 关闭连接
                if self.j_link.connected():
                    self.j_link.close()
                    self.f_logFunc("已断开J-Link连接")

                self.j_link = None  # 清除引用
            return True
        except Exception as e:
            self.f_logFunc(f"断开连接时出错: {str(e)}")
            return False

    # 完全关闭J-Link连接函数
    def f_shutdownFunc(self):
        """
        function:  完全关闭J-Link连接
              in:  无
             out:  无
          return:  成功返回True，否则返回False
          others:  释放所有资源
        """
        try:
            self.f_logFunc("正在关闭 J-Link 连接...")
            self.f_stopMonitoringFunc()  # 停止监控

            # 停止RTT
            if self.rtt_reader:
                self.rtt_reader.f_stopRttFunc()
                self.rtt_active = False
                self.f_logFunc("已停止 RTT 通信")

            if self.j_link:
                if self.j_link.connected():
                    try:
                        self.j_link.close()  # 正常关闭
                    except Exception as e:
                        self.f_logFunc(f"正常关闭失败: {str(e)}, 尝试强制关闭")
                        # 强制关闭
                        try:
                            self.j_link.close()
                        except:
                            pass
                self.j_link = None  # 清除引用

            return True
        except Exception as e:
            self.f_logFunc(f"关闭过程中发生错误: {str(e)}")
            return False

    # </editor-fold>

    # <editor-fold desc="获取适配器信息函数">
    # 获取支持的设备列表函数
    def f_listSupportedDevicesFunc(self):
        """
        function:  获取支持的设备列表
              in:  无
             out:  无
          return:  无
          others:  通过JLink命令行工具获取设备列表
        """

        def _list_devices():
            """内部设备列表获取函数"""
            try:
                jlink_exe = os.path.join(j_link_dir, "JLink.exe")  # JLink可执行文件路径
                command = f'"{jlink_exe}" -device ?'  # 命令行命令
                # 执行命令并捕获输出
                result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=10)

                devices = []  # 设备列表
                lines = result.stdout.splitlines()  # 分割输出行
                start_parsing = False  # 解析开始标志

                # 解析输出
                for line in lines:
                    if "Available devices:" in line:  # 找到设备列表开始
                        start_parsing = True
                        continue
                    if "J-Link>" in line or "Exit" in line:  # 列表结束标志
                        start_parsing = False
                    if start_parsing and line.strip():  # 处理有效行
                        if ":" in line:  # 格式化为"索引:设备名"
                            device_name = line.split(":", 1)[1].strip()
                            devices.append(device_name)
                        else:
                            devices.append(line.strip())  # 直接添加设备名

                # 备用解析方案
                if not devices:
                    for line in lines:
                        line = line.strip()
                        # 跳过无效行
                        if not line or line.startswith("J-Link>") or line.startswith("SEGGER"):
                            continue
                        if "Unknown command" in line or "Available devices" in line:
                            continue
                        devices.append(line)  # 添加设备名

                return devices  # 返回设备列表
            except Exception as e:
                self.f_logFunc(f"获取设备列表失败: {str(e)}")
                return []

        with self.lock:  # 线程安全
            devices = self.__f_executeWithRetryFunc(_list_devices)  # 执行获取
            self.list_devices_result.emit(devices or [])  # 发射结果信号

    # 刷新适配器信息函数
    def f_refreshAdapterInfoFunc(self):
        """
        function:  刷新适配器信息
              in:  无
             out:  无
          return:  无
          others:  获取并发射J-Link适配器信息
        """

        def _refresh():
            """内部刷新函数"""
            if not self.j_link:  # 检查连接
                return None

            try:
                # 构建信息字典
                info = {
                    "type": "JLINK",
                    "serial": str(self.j_link.serial_number),  # 序列号
                    "hw_version": str(self.j_link.hardware_version),  # 硬件版本
                    "dll_version": "未知",  # DLL版本(默认值)
                    "speed": "未知"  # 速度(默认值)
                }

                # 获取DLL版本
                try:
                    if hasattr(self.j_link, 'dll_version'):  # 检查属性存在
                        info["dll_version"] = str(self.j_link.dll_version())
                    elif hasattr(self.j_link, 'version_strings'):  # 备用方法
                        versions = self.j_link.version_strings
                        if isinstance(versions, dict) and 'dll' in versions:  # 字典格式
                            info["dll_version"] = str(versions['dll'])
                        elif isinstance(versions, str) and "DLL version" in versions:  # 字符串格式
                            for line in versions.splitlines():  # 逐行解析
                                if "DLL version" in line:
                                    dll_version = line.split("DLL version")[1].strip()
                                    info["dll_version"] = dll_version
                                    break
                except:
                    pass  # 忽略版本获取错误

                # 获取速度信息
                try:
                    speed = self.j_link.speed  # 获取当前速度
                    if speed:
                        info["speed"] = f"{speed // 1000} kHz"  # 转换为kHz字符串
                except:
                    pass  # 忽略速度获取错误

                return info  # 返回信息字典
            except Exception as e:
                self.f_logFunc(f"刷新适配器信息失败: {str(e)}")
                return None

        with self.lock:  # 线程安全
            info = self.__f_executeWithRetryFunc(_refresh)  # 执行刷新
            if info:  # 如果有有效信息
                # 发射适配器信息信号
                self.adapter_info_ready.emit(
                    info["type"], info["serial"], info["hw_version"],
                    info["dll_version"], info["speed"]
                )

    # </editor-fold>

    # <editor-fold desc="读取芯片相关信息">
    # 读取芯片ID函数
    def f_readChipIdFunc(self):
        """
        function:  读取芯片ID
              in:  无
             out:  无
          return:  无
          others:  尝试多种方法读取芯片ID
        """

        def _read():
            """内部读取函数"""
            try:
                id_value = self.j_link.core_id()  # 核心ID方法
                return f"0x{id_value:08X}"  # 格式化十六进制
            except:
                # 尝试常见ID地址
                for addr in [0x00000098, 0xE0042000, 0x40015800, 0x1FFFF7E8, 0x1FFFF7E0]:
                    try:
                        id_value = self.j_link.memory_read32(addr, 1)[0]  # 32位读取
                        return f"0x{id_value:08X}"  # 格式化十六进制
                    except:
                        continue  # 尝试下一个地址
                return "读取失败"  # 所有尝试失败

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                # 带重试执行读取
                chip_id = self.__f_executeWithRetryFunc(_read, max_retries=5, delay=0.1)
                # 发射芯片信息信号(ID部分)
                self.chip_info_ready.emit("", chip_id, "", "")

    # 读取芯片Flash大小函数
    def f_readFlashSizeFunc(self):
        """
        function:  读取Flash大小
              in:  无
             out:  无
          return:  无
          others:  尝试多种方法读取Flash大小
        """

        def _read():
            """内部读取函数"""
            # 尝试常见Flash大小地址
            for addr in [0x0000009C, 0x1FFFF7E0, 0x1FFF75E0]:
                try:
                    size = self.j_link.memory_read32(addr, 1)[0]  # 32位读取
                    if size > 0xFFFF:  # 值过大
                        size = self.j_link.memory_read16(addr, 1)[0]  # 尝试16位
                    if size > 0xFF:  # 值仍过大
                        size = self.j_link.memory_read8(addr, 1)[0]  # 尝试8位
                    return f"{size} KB"  # 返回带单位的大小
                except:
                    continue  # 尝试下一个地址
            return "读取失败"  # 所有尝试失败

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                # 带重试执行读取
                flash_size = self.__f_executeWithRetryFunc(_read, max_retries=5, delay=0.1)
                # 发射芯片信息信号(Flash大小部分)
                self.chip_info_ready.emit("", "", flash_size, "")

    # 读取芯片系统时钟配置函数
    def f_readSysClkCfgFunc(self):
        """
        function:  读取系统时钟配置
              in:  无
             out:  无
          return:  无
          others:  尝试多种方法读取时钟配置寄存器
        """

        def _read():
            """内部读取函数"""
            # 尝试常见时钟配置地址
            for addr in [0x40000080, 0x40021004, 0x40023808]:
                try:
                    value = self.j_link.memory_read32(addr, 1)[0]  # 32位读取
                    # 检查有效值
                    if value != 0 and value != 0xFFFFFFFF:
                        return f"0x{value:08X}"  # 格式化十六进制
                except:
                    continue  # 尝试下一个地址
            return "读取失败"  # 所有尝试失败

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                # 带重试执行读取
                clk_cfg = self.__f_executeWithRetryFunc(_read, max_retries=5, delay=0.1)
                # 发射芯片信息信号(时钟配置部分)
                self.chip_info_ready.emit("", "", "", clk_cfg)

    # </editor-fold>

    # <editor-fold desc="读取/写入内存函数">
    # 读取内存值函数
    def f_readMemoryFunc(self, address, size):
        """
        function:  读取内存值
              in:  address: 内存地址
                   size: 要读取的大小
             out:  无
          return:  读取到的值
          others:  读取指定地址和大小的内存值
        """

        def _read():
            try:
                # 读取内存数据
                data = self.j_link.memory_read(address, size)

                # 转换为整数
                if size == 1:
                    return data[0]
                elif size == 2:
                    return (data[1] << 8) | data[0]
                elif size == 4:
                    return (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]
                else:
                    return 0
            except Exception as e:
                self.f_logFunc(f"读取内存失败: {str(e)}")
                return 0

        with self.lock:
            if self.__f_ensureConnectedFunc():
                return self.__f_executeWithRetryFunc(_read, max_retries=3, delay=0.05)
            return 0

    # 写入芯片内存函数
    def f_writeMemoryFunc(self, address, data_str):
        """
        function:  写入内存
              in:  address: 内存地址(字符串)
                   data_str: 要写入的数据(字符串)
             out:  无
          return:  无
          others:  将数据写入指定内存地址
        """

        def _write():
            """内部写入函数"""
            # 解析地址和数据
            addr = int(address, 16 if address.startswith("0x") else 10)
            data = int(data_str, 16 if data_str.startswith("0x") else 10)
            # 写入内存(转换为4字节小端序)
            self.j_link.memory_write(addr, [data.to_bytes(4, 'little')])
            return (addr, data)  # 返回地址和数据

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                try:
                    # 带重试执行写入
                    addr, data = self.__f_executeWithRetryFunc(_write, max_retries=3, delay=0.05)
                    # 发射内存写入完成信号
                    self.memory_write_done.emit(addr, data)
                except Exception as e:
                    self.error_occurred.emit(f"写入内存失败: {str(e)}")  # 错误信号

    # 读取单个寄存器函数
    def f_readSingleRegisterFunc(self, address):
        """
        function:  读取单个寄存器
              in:  address: 寄存器地址(字符串)
             out:  无
          return:  无
          others:  支持不同大小的寄存器读取
        """

        def _read():
            """内部读取函数"""
            addr = int(address, 16 if address.startswith("0x") else 10)  # 解析地址
            try:
                data = self.j_link.memory_read(addr, 4)  # 尝试4字节读取
                return (addr, int.from_bytes(data, 'little'))  # 返回地址和值
            except:
                try:
                    data = self.j_link.memory_read(addr, 2)  # 尝试2字节读取
                    return (addr, int.from_bytes(data, 'little'))
                except:
                    data = self.j_link.memory_read(addr, 1)  # 尝试1字节读取
                    return (addr, int.from_bytes(data, 'little'))

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                try:
                    # 带重试执行读取
                    addr, value = self.__f_executeWithRetryFunc(_read, max_retries=3, delay=0.05)
                    # 发射寄存器读取信号
                    self.register_read.emit(addr, value)
                except Exception as e:
                    self.error_occurred.emit(f"读取寄存器失败: {str(e)}")  # 错误信号

    # 写入内存(原始字节)函数
    def f_writeMemoryBytesFunc(self, address, data_bytes):
        """
        function:  写入内存(原始字节)
              in:  address: 内存地址
                   data_bytes: 字节数据
             out:  无
          return:  成功返回True，否则返回False
          others:  直接写入原始字节数据
        """

        def _write():
            """内部写入函数"""
            if not self.__f_ensureConnectedFunc():  # 确保连接
                return False
            try:
                # 将字节转换为整数列表
                data_list = list(data_bytes)
                # 写入内存
                self.j_link.memory_write(address, data_list)
                return True  # 写入成功
            except Exception as e:
                self.error_occurred.emit(f"写入内存失败: {str(e)}")  # 错误信号
                return False  # 写入失败

        with self.lock:  # 线程安全
            return self.__f_executeWithRetryFunc(_write)  # 带重试执行

    # </editor-fold>

    # <editor-fold desc="监控参数相关函数">
    # 开始监控参数函数
    def f_startMonitoringFunc(self, params):
        """
        function:  开始监控参数
              in:  params: 要监控的参数列表
             out:  无
          return:  成功返回True，否则返回False
          others:  支持RTT和异步双模式
        """

        def _start():
            """内部启动函数"""
            # 停止现有监控
            if self.monitoring_active:
                self.f_stopMonitoringFunc()

            valid_params = []  # 有效参数列表
            # 验证每个参数
            for param in params:
                try:
                    # 确保参数有所有必要字段
                    if 'addr' in param and 'size' in param and 'type' in param:
                        valid_params.append(param)
                    else:
                        self.f_logFunc(f"参数 {param.get('name', '未知')} 缺少必要字段，将被忽略")
                except:
                    self.f_logFunc(f"参数 {param.get('name', '未知')} 无效，将被忽略")
                    continue

            # 检查是否有有效参数
            if not valid_params:
                self.f_logFunc("没有有效参数可监控")
                return False

            # 停止现有定时器
            if self.monitor_timer:
                self.monitor_timer.stop()
                self.monitor_timer = None

            # 设置监控状态
            self.monitored_params = valid_params
            self.monitoring_active = True
            self.monitor_timer = QTimer()  # 创建新定时器
            self.monitor_timer.timeout.connect(self.f_readMonitoredParamsFunc)  # 连接槽函数

            # 根据模式设置定时器间隔
            if self.read_mode == "rtt":  # RTT模式
                self.monitor_timer.start(5)  # 5ms间隔
            else:  # 异步模式
                self.monitor_timer.start(10)  # 10ms间隔

            return True  # 启动成功

        with self.lock:  # 线程安全
            if self.__f_ensureConnectedFunc():  # 确保连接
                if self.__f_executeWithRetryFunc(_start):  # 启动监控
                    self.monitoring_status.emit(True)  # 发射状态信号
                    return True
            return False  # 启动失败

    # 停止监控函数
    def f_stopMonitoringFunc(self):
        """
        function:  停止监控
              in:  无
             out:  无
          return:  成功返回True，否则返回False
          others:  停止定时器并重置状态
        """

        def _stop():
            """内部停止函数"""
            if self.monitor_timer:
                self.monitor_timer.stop()
                self.monitor_timer = None

            self.monitoring_active = False
            self.monitored_params = []  # 清空参数列表
            try:
                # 如果芯片暂停则复位
                if self.j_link and self.j_link.halted():
                    self.j_link.reset(halt=False)
            except:
                pass
            return True

        with self.lock:  # 线程安全
            if self.__f_executeWithRetryFunc(_stop):  # 执行停止
                self.monitoring_status.emit(False)  # 发射状态信号
                return True
            return False

    # 读取监控参数函数(双模式)
    def f_readMonitoredParamsFunc(self):
        """
        function:  读取监控参数(双模式)
              in:  无
             out:  无
          return:  无
          others:  根据当前模式调用RTT或异步读取
        """
        # 长时间无成功读取时尝试恢复连接
        if time.time() - self.last_successful_read > 10 and self.read_failure_count > 0:
            self.f_logFunc("长时间无成功读取，尝试恢复连接...")
            if self._connection_params:  # 有连接参数
                # 尝试重新连接
                self.f_connectJLinkFunc(
                    self._connection_params["device"],
                    self._connection_params["interface"],
                    self._connection_params["speed"]
                )
            self.read_failure_count = 0  # 重置计数器
            self.last_successful_read = time.time()  # 更新最后成功时间

        # 根据模式选择读取方法
        if self.read_mode == "rtt" and self.rtt_active:  # RTT模式
            param_values = self.__f_readRttParametersFunc()
        else:  # 异步模式
            param_values = self.__f_readAsyncParametersFunc()

        # 如果有有效结果则发射信号
        if param_values:
            self.param_values_ready.emit(param_values)
        elif self.monitoring_active:  # 空结果且监控激活
            self.read_failure_count += 1  # 增加失败计数

            # 每5次失败记录一次
            if self.read_failure_count % 5 == 0:
                self.f_logFunc(f"连续读取失败 {self.read_failure_count} 次")

    # </editor-fold>

    # <editor-fold desc="设置监控参数">
    # 设置监控间隔函数
    def f_setMonitoringIntervalFunc(self, interval_seconds):
        """
        function:  设置监控间隔
              in:  interval_seconds: 间隔时间(秒)
             out:  无
          return:  成功返回True，否则返回False
          others:  动态调整监控频率
        """
        with self.lock:  # 线程安全
            if self.monitoring_active and self.monitor_timer:
                self.monitor_timer.stop()  # 停止当前定时器

                # 创建新定时器
                self.monitor_timer = QTimer()
                self.monitor_timer.timeout.connect(self.f_readMonitoredParamsFunc)
                # 启动定时器(转换为毫秒)
                self.monitor_timer.start(int(interval_seconds * 1000))

                self.f_logFunc(f"监控间隔已更新为: {interval_seconds:.3f} 秒")
                return True
        return False

    # 设置刷新率函数
    def f_setRefreshRateFunc(self, rate_hz):
        """
        function:  设置数据采集刷新率
              in:  rate_hz: 刷新率(Hz)
             out:  无
          return:  无
          others:  通过信号在主线程更新定时器
        """
        self.f_logFunc(f"设置数据采集刷新率为: {rate_hz} Hz")
        with self.lock:  # 线程安全
            if self.monitoring_active:  # 监控激活
                # 使用信号在主线程安全更新定时器
                self.monitor_timer_updated.emit(rate_hz)

    # </editor-fold>

    # <editor-fold desc="私有方法">
    # 尝试连接Cortex-M系列设备
    def __f_connectCortexMFunc(self, device, speed):
        """
        function:  尝试连接Cortex-M系列设备
              in:  device: 原始设备名称
                   speed: 连接速度(kHz)
             out:  无
          return:  连接成功返回True，否则返回False
          others:  用于处理不支持的设备名称
        """
        cortex_devices = [
            "Cortex-M0", "Cortex-M1", "Cortex-M3",
            "Cortex-M4", "Cortex-M7", "Cortex-M23", "Cortex-M33"
        ]

        # 尝试常见Cortex设备
        for cortex in cortex_devices:
            try:
                self.j_link.connect(cortex, speed)  # 尝试连接
                self.f_logFunc(f"成功连接到 {cortex}")  # 记录成功日志
                return True
            except:
                continue  # 尝试下一个设备
        return False  # 所有尝试均失败

    # 连接后设置函数
    def __f_postConnectSetupFunc(self):
        """
        function:  连接后设置
              in:  无
             out:  无
          return:  无
          others:  执行目标芯片复位和暂停
        """
        self.f_logFunc("执行目标芯片复位...")
        try:
            self.j_link.reset(halt=True)  # 复位并暂停芯片
        except:
            self.f_logFunc("硬件复位失败，尝试软件复位...")
            self.j_link.set_reset_strategy(1)  # 设置复位策略
            self.j_link.reset(halt=True)  # 再次尝试复位

        self.f_logFunc("暂停目标芯片...")
        self.j_link.halt()  # 暂停芯片

        # 验证连接状态
        if not self.j_link.target_connected():
            raise Exception("目标芯片未响应")

        # 优化连接速度
        self.__f_optimizeSpeedFunc()

    # 优化速度函数
    def __f_optimizeSpeedFunc(self):
        """
        function:  优化连接速度
              in:  无
             out:  无
          return:  无
          others:  通过测试读取动态调整连接速度
        """
        test_addr = 0x20000000  # 测试地址
        try:
            # 尝试读取内存
            self.j_link.memory_read(test_addr, 4)
            # 如果速度较低且不是旧驱动，尝试提高速度
            if self._optimal_speed < 10000 and not self.old_driver:
                self._optimal_speed = min(10000, self._optimal_speed * 2)
                self.f_logFunc(f"提高接口速度到 {self._optimal_speed} kHz")
                self.j_link.set_speed(self._optimal_speed)  # 设置新速度
        except:
            # 读取失败则降低速度
            self._optimal_speed = max(1000, self._optimal_speed // 2)
            self.f_logFunc(f"降低接口速度到 {self._optimal_speed} kHz")
            self.j_link.set_speed(self._optimal_speed)

    # 异步读取参数值函数
    def __f_readAsyncParametersFunc(self):
        """
        function:  异步读取参数值
              in:  无
             out:  无
          return:  参数值字典
          others:  优化的批量读取方法，无暂停操作
        """
        # 检查监控状态
        if not self.monitoring_active or not self.monitored_params or not self.j_link:
            return {}

        param_values = {}  # 参数值字典，键为地址

        try:
            # 确保连接
            if not self.__f_ensureConnectedFunc():
                return {}

            # 检测驱动版本
            self.old_driver = not hasattr(self.j_link, 'set_timeout')

            # 使用批量读取方法
            param_values = self.__f_readBatchMemoryFunc()

            # 重置失败计数器
            self.read_failure_count = 0
            self.last_successful_read = time.time()
            return param_values
        except Exception as e:
            # 处理读取错误
            self.read_failure_count += 1
            self.f_logFunc(f"异步读取错误 #{self.read_failure_count}: {str(e)}")

            # 失败超过5次尝试重新连接
            if self.read_failure_count >= 5:
                self.f_logFunc("连续读取失败超过5次，尝试重新连接...")
                self.read_failure_count = 0
                if self._connection_params:  # 有连接参数
                    # 尝试重新连接
                    self.f_connectJLinkFunc(
                        self._connection_params["device"],
                        self._connection_params["interface"],
                        self._connection_params["speed"]
                    )
            return {}  # 返回空字典

    # 批量读取内存函数
    def __f_readBatchMemoryFunc(self):
        """
        function:  批量读取内存
              in:  无
             out:  无
          return:  参数值字典，键为地址
          others:  优化内存读取，减少访问次数
        """
        param_values = {}
        addresses = []
        param_map = {}
        read_errors = []

        # 收集所有需要读取的地址和参数信息
        for param in self.monitored_params:
            try:
                addr = int(param['addr'], 16)
                addresses.append(addr)
                # 存储地址、大小和参数信息
                param_map[addr] = (param, int(param['size']))
            except Exception as e:
                read_errors.append(f"地址错误 ({str(e)})")
                continue

        # 无有效地址则返回
        if not addresses:
            return {}

        # 排序并去重地址
        addresses = sorted(set(addresses))

        try:
            # 分批读取(每批最多8个地址)
            for i in range(0, len(addresses), 8):
                batch = addresses[i:i + 8]
                start_addr = min(batch)
                end_addr = max(batch)

                # 计算最大需要读取的大小
                max_size = max(param_map[addr][1] for addr in batch)
                size = end_addr - start_addr + max_size

                try:
                    # 读取整个内存块
                    data = self.j_link.memory_read(start_addr, size)

                    # 处理批次中的每个地址
                    for addr in batch:
                        param, param_size = param_map[addr]
                        offset = addr - start_addr

                        # 检查偏移是否有效
                        if offset + param_size > len(data):
                            read_errors.append(f"读取越界")
                            continue

                        # 提取指定长度的字节
                        data_bytes = bytes(data[offset:offset + param_size])
                        value = self.__f_parseDataBytesFunc(data_bytes, param)

                        # 使用地址作为键
                        param_values[param['addr']] = value
                except Exception as e:
                    # 批量读取失败，回退到逐个读取
                    for addr in batch:
                        param, param_size = param_map[addr]
                        try:
                            # 读取指定长度的内存
                            data = self.j_link.memory_read(addr, param_size)
                            data_bytes = bytes(data)
                            value = self.__f_parseDataBytesFunc(data_bytes, param)
                            param_values[param['addr']] = value
                        except Exception as e:
                            read_errors.append(f"读取失败 ({str(e)})")

            # 记录读取错误
            if read_errors:
                self.f_logFunc(f"部分参数读取失败: {', '.join(read_errors[:3])}" +
                               ("..." if len(read_errors) > 3 else ""))

            return param_values
        except Exception as e:
            self.f_logFunc(f"批量读取内存失败: {str(e)}")
            # 回退到逐个读取
            return self.__f_readParamsIndividuallyFunc()

    # 新增：解析字节数据函数
    def __f_parseDataBytesFunc(self, data_bytes, param):
        """根据数据类型解析字节数据，考虑数据长度"""
        dtype = param['type']
        size = len(data_bytes)

        try:
            # 根据数据类型解析值
            if dtype == 'u8':  # 8位无符号
                return data_bytes[0] if size >= 1 else 0
            elif dtype == 'u16':  # 16位无符号
                return struct.unpack('<H', data_bytes[:2])[0] if size >= 2 else 0
            elif dtype == 's16':  # 16位有符号
                return struct.unpack('<h', data_bytes[:2])[0] if size >= 2 else 0
            elif dtype == 'float':  # 单精度浮点
                # 确保有4字节数据
                if size < 4:
                    # 不足4字节则填充0
                    padded_bytes = data_bytes + bytes(4 - size)
                    return struct.unpack('<f', padded_bytes)[0]
                return struct.unpack('<f', data_bytes[:4])[0]
            elif dtype == 's32':  # 32位有符号
                if size < 4:
                    padded_bytes = data_bytes + bytes(4 - size)
                    return struct.unpack('<i', padded_bytes)[0]
                return struct.unpack('<i', data_bytes)[0]
            else:  # 默认32位无符号
                if size < 4:
                    padded_bytes = data_bytes + bytes(4 - size)
                    return struct.unpack('<I', padded_bytes)[0]
                return struct.unpack('<I', data_bytes)[0]
        except Exception as e:
            self.f_logFunc(f"解析参数 {param['name']} 失败: {str(e)}")
            return 0

    # 逐个读取参数函数
    def __f_readParamsIndividuallyFunc(self):
        """
        function:  逐个读取参数
              in:  无
             out:  无
          return:  参数值字典，键为地址
          others:  最终回退方案，无暂停操作
        """
        param_values = {}
        read_errors = []

        # 遍历每个参数
        for param in self.monitored_params:
            try:
                addr = int(param['addr'], 16)  # 解析地址
                size = int(param['size'])  # 获取数据长度
                dtype = param['type']  # 数据类型

                try:
                    # 根据size读取内存
                    data = self.j_link.memory_read(addr, size)
                    data_bytes = bytes(data)
                except Exception as e:
                    read_errors.append(f"读取失败 ({str(e)})")
                    continue

                # 使用统一解析函数
                value = self.__f_parseDataBytesFunc(data_bytes, param)
                param_values[param['addr']] = value
            except Exception as e:
                read_errors.append(f"地址错误 ({str(e)})")

        # 记录读取错误
        if read_errors:
            self.f_logMessageFunc(f"部分参数读取失败: {', '.join(read_errors[:3])}" +
                                  ("..." if len(read_errors) > 3 else ""))

        return param_values

    # 确保连接状态函数
    def __f_ensureConnectedFunc(self):
        """
        function:  确保连接状态
              in:  无
             out:  无
          return:  已连接返回True，否则尝试重连
          others:  支持自动重连功能
        """
        # 检查连接状态
        if not self.j_link or not self.j_link.connected():
            self.f_logFunc("连接已断开，尝试重新连接...")
            if not self._connection_params:  # 无连接参数
                return False

            # 尝试重新连接
            success = self.f_connectJLinkFunc(
                self._connection_params["device"],
                self._connection_params["interface"],
                self._connection_params["speed"]
            )

            # 重连后等待稳定
            if success:
                time.sleep(1)
            return success
        return True  # 已连接

    # 带重试执行函数
    @staticmethod
    def __f_executeWithRetryFunc(func, max_retries=3, delay=0.1):
        """
        function:  带重试执行函数
              in:  func: 要执行的函数
                   max_retries: 最大重试次数(默认3)
                   delay: 初始延迟(秒，默认0.1)
             out:  无
          return:  函数返回值或None
          others:  使用指数退避策略
        """
        # 指数退避重试
        for attempt in range(max_retries):
            try:
                return func()  # 尝试执行函数
            except Exception as e:
                if attempt == max_retries - 1:  # 最后一次尝试
                    raise  # 抛出异常
                wait_time = delay * (2 ** attempt)  # 指数退避计算等待时间
                time.sleep(wait_time)  # 等待
        return None  # 重试失败

    # 安全暂停目标芯片函数
    def __f_safeHaltTargetFunc(self, max_retries=10):
        """
        function:  安全暂停目标芯片
              in:  max_retries: 最大重试次数(默认10)
             out:  无
          return:  成功返回True，否则返回False
          others:  解决低功耗模式无法连接问题
        """
        try:
            # 检查暂停状态
            if hasattr(self.j_link, 'halted'):  # 新驱动支持
                was_halted = self.j_link.halted()
            else:  # 旧驱动回退
                was_halted = False

            if was_halted:  # 已暂停
                return True
        except:
            was_halted = False

        # 尝试暂停芯片
        for attempt in range(max_retries):
            try:
                # 复位并暂停
                self.j_link.reset(halt=True)
                time.sleep(0.1 * (attempt + 1))  # 等待时间递增

                # 检查暂停状态
                if hasattr(self.j_link, 'halted') and self.j_link.halted():
                    return True
                else:  # 旧驱动无法检测状态
                    return True  # 假设成功

            except Exception as e:
                self.f_logFunc(f"暂停芯片失败，尝试 #{attempt + 1}: {str(e)}")
                time.sleep(0.2)  # 失败后等待更长时间

        self.f_logFunc("暂停芯片失败，已达最大重试次数")
        return False  # 暂停失败

    # </editor-fold>

    # <editor-fold desc="RTT相关函数">
    # 设置RTT控制块地址函数
    def f_setRttControlBlockFunc(self, address):
        """
        function:  设置RTT控制块地址
              in:  address: 十六进制或十进制格式的地址字符串
             out:  无
          return:  True表示成功设置，False表示失败
          others:  将字符串地址转换为整数
        """
        try:
            # 解析地址（支持十六进制和十进制）
            addr = int(address, 16 if address.startswith("0x") else 10)
            self.rtt_control_block_addr = addr  # 存储控制块地址
            return True  # 设置成功
        except:
            return False  # 设置失败

    # 使用RTT读取参数值函数
    def __f_readRttParametersFunc(self):
        """
        function:  使用RTT读取参数值
              in:  无
             out:  无
          return:  参数值字典
          others:  从RTT缓冲区批量读取参数
        """
        if not self.rtt_active or not self.monitoring_active:  # 检查状态
            return {}

        try:
            # 计算需要读取的总字节数(每个参数4字节)
            total_size = len(self.monitored_params) * 4
            # 从RTT缓冲区0读取数据
            data = self.rtt_reader.f_readRttFunc(0, total_size)
            if not data or len(data) < total_size:  # 检查数据有效性
                return {}

            param_values = {}  # 参数值字典

            # 处理每个参数
            for param in self.monitored_params:
                param_name = param['name']  # 参数名
                dtype = param['type']  # 数据类型
                offset = param.get('offset', 0)  # 数据偏移量
                value_bytes = data[offset:offset + 4]  # 提取字节数据

                try:
                    # 根据数据类型解析值
                    if dtype == 'u8':  # 8位无符号
                        value = value_bytes[0]
                    elif dtype == 'u16':  # 16位无符号
                        value = struct.unpack('<H', value_bytes[:2])[0]
                    elif dtype == 's16':  # 16位有符号
                        value = struct.unpack('<h', value_bytes[:2])[0]
                    elif dtype == 's32':  # 32位有符号
                        value = struct.unpack('<i', value_bytes)[0]
                    elif dtype == 'float':  # 单精度浮点
                        value = struct.unpack('<f', value_bytes)[0]
                    else:  # 默认32位无符号
                        value = struct.unpack('<I', value_bytes)[0]

                    param_values[param_name] = value  # 存储值
                except:
                    param_values[param_name] = None  # 解析失败

            return param_values  # 返回参数值字典
        except Exception as e:
            self.f_logFunc(f"RTT读取错误: {str(e)}")
            return {}  # 读取失败

    # </editor-fold>

    # <editor-fold desc="加载参数配置文件">
    # 加载JSON配置文件函数
    def f_loadJsonConfigFunc(self, file_path):
        """
        function:  加载JSON配置文件
              in:  file_path: JSON文件路径
             out:  无
          return:  加载的配置字典或None
          others:  加载参数配置文件
        """

        def _load():
            """内部加载函数"""
            with open(file_path, 'r', encoding="utf-8") as f:  # 打开文件
                return json.load(f)  # 加载JSON

        with self.lock:  # 线程安全
            try:
                # 带重试执行加载
                self.params_config = self.__f_executeWithRetryFunc(_load)
                return self.params_config  # 返回配置
            except Exception as e:
                self.f_logFunc(f"加载JSON配置失败: {str(e)}")
                return None  # 加载失败
    # </editor-fold>
